<!DOCTYPE html>
<!-- saved from url=(0046)https://mybatis.org/mybatis-3/zh/java-api.html -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh" lang="zh"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="author" content="Clinton Begin">
    <meta name="author" content="Nan Lei">
    <meta name="Date-Revision-yyyymmdd" content="20200309">
    <meta http-equiv="Content-Language" content="zh">
    <title>mybatis – MyBatis 3 | Java API</title>
    <link rel="stylesheet" href="./mybatis – MyBatis 3 _ Java API_files/apache-maven-fluido-1.7.min.css">
    <link rel="stylesheet" href="./mybatis – MyBatis 3 _ Java API_files/site.css">
    <link rel="stylesheet" href="./mybatis – MyBatis 3 _ Java API_files/print.css" media="print">
    <script type="text/javascript" src="./mybatis – MyBatis 3 _ Java API_files/apache-maven-fluido-1.7.min.js.下载"></script>
  </head>
  <body class="topBarDisabled">
    <div class="container-fluid">
      <div id="banner">
        <div class="pull-left"><div id="bannerLeft"><h2>mybatis</h2>
</div>
</div>
        <div class="pull-right"><a href="https://mybatis.org/" id="bannerRight" title="MyBatis logo"><img src="./mybatis – MyBatis 3 _ Java API_files/mybatis-logo.png" alt="MyBatis logo"></a></div>
        <div class="clear"><hr></div>
      </div>

      <div id="breadcrumbs">
        <ul class="breadcrumb">
        <li id="publishDate">最近更新: 09 三月 2020<span class="divider">|</span>
</li>
          <li id="projectVersion">版本: 3.5.4</li>
        </ul>
      </div>
      <div class="row-fluid">
        <div id="leftColumn" class="span2">
          <div class="well sidebar-nav">
    <ul class="nav nav-list">
      <li class="nav-header">参考文档</li>
    <li><a href="https://mybatis.org/mybatis-3/zh/index.html" title="简介"><span class="none"></span>简介</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/getting-started.html" title="入门"><span class="none"></span>入门</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/configuration.html" title="XML 配置"><span class="icon-chevron-right"></span>XML 配置</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/sqlmap-xml.html" title="XML 映射文件"><span class="icon-chevron-right"></span>XML 映射文件</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/dynamic-sql.html" title="动态 SQL"><span class="none"></span>动态 SQL</a></li>
    <li class="active"><a href="https://mybatis.org/mybatis-3/zh/java-api.html#"><span class="icon-chevron-down"></span>Java API</a>
    <ul class="nav nav-list">
    <li><a href="https://mybatis.org/mybatis-3/zh/java-api.html#directoryStructure" title="目录结构"><span class="none"></span>目录结构</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/java-api.html#sqlSessions" title="SqlSession"><span class="none"></span>SqlSession</a></li>
    </ul>
</li>
    <li><a href="https://mybatis.org/mybatis-3/zh/statement-builders.html" title="SQL 语句构建器"><span class="none"></span>SQL 语句构建器</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/logging.html" title="日志"><span class="none"></span>日志</a></li>
      <li class="nav-header">项目文档</li>
    <li><a href="https://mybatis.org/mybatis-3/zh/project-info.html" title="项目信息"><span class="icon-chevron-right"></span>项目信息</a></li>
    <li><a href="https://mybatis.org/mybatis-3/zh/project-reports.html" title="项目报表"><span class="icon-chevron-right"></span>项目报表</a></li>
</ul>
          <hr>
          <div id="poweredBy">
            <div class="clear"></div>
            <div class="clear"></div>
            <div class="clear"></div>
            <div class="clear"></div>
<a href="http://maven.apache.org/" title="构建依靠 Maven" class="poweredBy"><img class="builtBy" alt="构建依靠 Maven" src="./mybatis – MyBatis 3 _ Java API_files/maven-feather.png"></a>
            </div>
          </div>
        </div>
        <div id="bodyColumn" class="span10">


  
  <a name="javaApi"></a>
<div class="section" id="javaApi">
<h2><a name="Java_API"></a>Java API</h2>
  
<p>既然你已经知道如何配置 MyBatis 以及如何创建映射，是时候来尝点甜头了。MyBatis 的 Java API 就是这个甜头。稍后你将看到，和 JDBC 相比，MyBatis
  大幅简化你的代码并力图保持其简洁、容易理解和维护。为了使得 SQL 映射更加优秀，MyBatis 3 引入了许多重要的改进。</p>

  <a name="directoryStructure"></a>
<div class="section" id="directoryStructure">
<h3><a name="a.E7.9B.AE.E5.BD.95.E7.BB.93.E6.9E.84"></a>目录结构</h3>
  
<p>在我们深入 Java API 之前，理解关于目录结构的最佳实践是很重要的。MyBatis 非常灵活，你可以随意安排你的文件。但和其它框架一样，目录结构有一种最佳实践。
  </p>
  
<p>
  让我们看一下典型的应用目录结构：
  </p>
  
<div>
<pre>/my_application
  /bin
  /devlib
  <b>/lib                <tt>&lt;-- MyBatis *.jar 文件在这里。</tt></b>
  /src
    /org/myapp/
      /action
      <b>/data           <tt>&lt;-- MyBatis 配置文件在这里，包括映射器类、XML 配置、XML 映射文件。</tt></b>
        /mybatis-config.xml
        /BlogMapper.java
        /BlogMapper.xml
      /model
      /service
      /view
    <b>/properties       <tt>&lt;-- 在 XML 配置中出现的属性值在这里。</tt></b>
  /test
    /org/myapp/
      /action
      /data
      /model
      /service
      /view
    /properties
  /web
    /WEB-INF
      /web.xml</pre></div>

<p>当然，这是推荐的目录结构，并非强制要求，但使用一个通用的目录结构将更有利于大家沟通。</p>

<p>本章接下来的示例将假定你遵循这种目录结构。</p>
  </div>

  <a name="sqlSessions"></a>
<div class="section" id="sqlSessions">
<h3><a name="SqlSession"></a>SqlSession</h3>
  
<p>使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令，获取映射器示例和管理事务。在介绍 SqlSession 接口之前，我们先来了解如何获取一个 SqlSession 实例。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的各种方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的，它可以从 XML、注解或 Java 配置代码来创建 SqlSessionFactory。</p>
  
<p>
  <span class="label important">提示</span> 当 Mybatis 与一些依赖注入框架（如 Spring 或者 Guice）搭配使用时，SqlSession 将被依赖注入框架创建并注入，所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory，可以直接阅读 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册以了解更多信息。</p>
  
<div class="section">
<h4><a name="SqlSessionFactoryBuilder"></a>SqlSessionFactoryBuilder</h4>
  
<p>SqlSessionFactoryBuilder 有五个 build() 方法，每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">SqlSessionFactory</span><span class="pln"> build</span><span class="pun">(</span><span class="typ">InputStream</span><span class="pln"> inputStream</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> build</span><span class="pun">(</span><span class="typ">InputStream</span><span class="pln"> inputStream</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> environment</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> build</span><span class="pun">(</span><span class="typ">InputStream</span><span class="pln"> inputStream</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Properties</span><span class="pln"> properties</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> build</span><span class="pun">(</span><span class="typ">InputStream</span><span class="pln"> inputStream</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> env</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Properties</span><span class="pln"> props</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> build</span><span class="pun">(</span><span class="typ">Configuration</span><span class="pln"> config</span><span class="pun">)</span></pre></div>
  
<p>第一种方法是最常用的，它接受一个指向 XML 文件（也就是之前讨论的 mybatis-config.xml 文件）的 InputStream 实例。可选的参数是 environment 和 properties。environment 决定加载哪种环境，包括数据源和事务管理器。比如：</p>

  
<div class="source"><pre class="prettyprint"><span class="tag">&lt;environments</span><span class="pln"> </span><span class="atn">default</span><span class="pun">=</span><span class="atv">"development"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;environment</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"development"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;transactionManager</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"JDBC"</span><span class="tag">&gt;</span><span class="pln">
        ...
    </span><span class="tag">&lt;dataSource</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"POOLED"</span><span class="tag">&gt;</span><span class="pln">
        ...
  </span><span class="tag">&lt;/environment&gt;</span><span class="pln">
  </span><span class="tag">&lt;environment</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"production"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;transactionManager</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"MANAGED"</span><span class="tag">&gt;</span><span class="pln">
        ...
    </span><span class="tag">&lt;dataSource</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"JNDI"</span><span class="tag">&gt;</span><span class="pln">
        ...
  </span><span class="tag">&lt;/environment&gt;</span><span class="pln">
</span><span class="tag">&lt;/environments&gt;</span></pre></div>
  
<p>如果你调用了带 environment 参数的 build 方法，那么 MyBatis 将使用该环境对应的配置。当然，如果你指定了一个无效的环境，会收到错误。如果你调用了不带 environment 参数的 build 方法，那么就会使用默认的环境配置（在上面的示例中，通过 default="development" 指定了默认环境）。</p>

  
<p>如果你调用了接受 properties 实例的方法，那么 MyBatis 就会加载这些属性，并在配置中提供使用。绝大多数场合下，可以用 ${propName} 形式引用这些配置值。</p>
  
<p>回想一下，在 mybatis-config.xml 中，可以引用属性值，也可以直接指定属性值。因此，理解属性的优先级是很重要的。在之前的文档中，我们已经介绍过了相关内容，但为了方便查阅，这里再重新介绍一下：</p>
<hr>
  
<p>如果一个属性存在于下面的多个位置，那么 MyBatis 将按照以下顺序来加载它们：</p>
  
<ul>
  
<li>首先，读取在 properties 元素体中指定的属性；</li>
  
<li>其次，读取在 properties 元素的类路径 resource 或 url 指定的属性，且会覆盖已经指定了的重复属性；</li>
  
<li>最后，读取作为方法参数传递的属性，且会覆盖已经从 properties 元素体和 resource 或 url 属性中加载了的重复属性。</li>
  </ul>
  
<p>因此，通过方法参数传递的属性的优先级最高，resource 或 url 指定的属性优先级中等，在 properties 元素体中指定的属性优先级最低。
  </p>
<hr>
  
<p>总结一下，前四个方法很大程度上是相同的，但提供了不同的覆盖选项，允许你可选地指定 environment 和/或 properties。以下给出一个从 mybatis-config.xml 文件创建 SqlSessionFactory 的示例：</p>

  
<div class="source"><pre class="prettyprint"><span class="typ">String</span><span class="pln"> </span><b><span class="pln">resource</span></b><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"org/mybatis/builder/mybatis-config.xml"</span><span class="pun">;</span><span class="pln">
</span><span class="typ">InputStream</span><span class="pln"> </span><b><span class="pln">inputStream</span></b><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Resources</span><span class="pun">.</span><span class="pln">getResourceAsStream</span><span class="pun">(</span><span class="pln">resource</span><span class="pun">);</span><span class="pln">
</span><span class="typ">SqlSessionFactoryBuilder</span><span class="pln"> </span><b><span class="pln">builder</span></b><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlSessionFactoryBuilder</span><span class="pun">();</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> </span><b><span class="pln">factory</span></b><span class="pln"> </span><span class="pun">=</span><span class="pln"> builder</span><span class="pun">.</span><span class="pln">build</span><span class="pun">(</span><span class="pln">inputStream</span><span class="pun">);</span></pre></div>
  
<p>注意，这里我们使用了 Resources 工具类，这个类在 org.apache.ibatis.io 包中。Resources 类正如其名，会帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。在略读该类的源代码或用 IDE 查看该类信息后，你会发现一整套相当实用的方法。这里给出一个简表：</p>
  
<div class="source"><pre class="prettyprint"><span class="pln">URL getResourceURL</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
URL getResourceURL</span><span class="pun">(</span><span class="typ">ClassLoader</span><span class="pln"> loader</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">InputStream</span><span class="pln"> getResourceAsStream</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">InputStream</span><span class="pln"> getResourceAsStream</span><span class="pun">(</span><span class="typ">ClassLoader</span><span class="pln"> loader</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Properties</span><span class="pln"> getResourceAsProperties</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Properties</span><span class="pln"> getResourceAsProperties</span><span class="pun">(</span><span class="typ">ClassLoader</span><span class="pln"> loader</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Reader</span><span class="pln"> getResourceAsReader</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Reader</span><span class="pln"> getResourceAsReader</span><span class="pun">(</span><span class="typ">ClassLoader</span><span class="pln"> loader</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">File</span><span class="pln"> getResourceAsFile</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">File</span><span class="pln"> getResourceAsFile</span><span class="pun">(</span><span class="typ">ClassLoader</span><span class="pln"> loader</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> resource</span><span class="pun">)</span><span class="pln">
</span><span class="typ">InputStream</span><span class="pln"> getUrlAsStream</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> urlString</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Reader</span><span class="pln"> getUrlAsReader</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> urlString</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Properties</span><span class="pln"> getUrlAsProperties</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> urlString</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Class</span><span class="pln"> classForName</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> className</span><span class="pun">)</span></pre></div>
  
<p>最后一个 build 方法接受一个 Configuration 实例。Configuration 类包含了对一个 SqlSessionFactory 实例你可能关心的所有内容。在检查配置时，Configuration 类很有用，它允许你查找和操纵 SQL 映射（但当应用开始接收请求时不推荐使用）。你之前学习过的所有配置开关都存在于 Configuration 类，只不过它们是以 Java API 形式暴露的。以下是一个简单的示例，演示如何手动配置 Configuration 实例，然后将它传递给 build() 方法来创建 SqlSessionFactory。</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">DataSource</span><span class="pln"> dataSource </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BaseDataTest</span><span class="pun">.</span><span class="pln">createBlogDataSource</span><span class="pun">();</span><span class="pln">
</span><span class="typ">TransactionFactory</span><span class="pln"> transactionFactory </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">JdbcTransactionFactory</span><span class="pun">();</span><span class="pln">

</span><span class="typ">Environment</span><span class="pln"> environment </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Environment</span><span class="pun">(</span><span class="str">"development"</span><span class="pun">,</span><span class="pln"> transactionFactory</span><span class="pun">,</span><span class="pln"> dataSource</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Configuration</span><span class="pln"> configuration </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Configuration</span><span class="pun">(</span><span class="pln">environment</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">setLazyLoadingEnabled</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">setEnhancementEnabled</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">getTypeAliasRegistry</span><span class="pun">().</span><span class="pln">registerAlias</span><span class="pun">(</span><span class="typ">Blog</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">getTypeAliasRegistry</span><span class="pun">().</span><span class="pln">registerAlias</span><span class="pun">(</span><span class="typ">Post</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">getTypeAliasRegistry</span><span class="pun">().</span><span class="pln">registerAlias</span><span class="pun">(</span><span class="typ">Author</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">addMapper</span><span class="pun">(</span><span class="typ">BoundBlogMapper</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
configuration</span><span class="pun">.</span><span class="pln">addMapper</span><span class="pun">(</span><span class="typ">BoundAuthorMapper</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

</span><span class="typ">SqlSessionFactoryBuilder</span><span class="pln"> builder </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">SqlSessionFactoryBuilder</span><span class="pun">();</span><span class="pln">
</span><span class="typ">SqlSessionFactory</span><span class="pln"> factory </span><span class="pun">=</span><span class="pln"> builder</span><span class="pun">.</span><span class="pln">build</span><span class="pun">(</span><span class="pln">configuration</span><span class="pun">);</span></pre></div>
  
<p>现在你就获得一个可以用来创建 SqlSession 实例的 SqlSessionFactory 了。</p>

  </div>
<div class="section">
<h4><a name="SqlSessionFactory"></a>SqlSessionFactory</h4>
  
<p>SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说，当你选择其中一个方法时，你需要考虑以下几点：</p>
  
<ul>
    
<li><b>事务处理</b>：你希望在 session 作用域中使用事务作用域，还是使用自动提交（auto-commit）？（对很多数据库和/或 JDBC 驱动来说，等同于关闭事务支持）</li>
    
<li><b>数据库连接</b>：你希望 MyBatis 帮你从已配置的数据源获取连接，还是使用自己提供的连接？</li>
    
<li><b>语句执行</b>：你希望 MyBatis 复用 PreparedStatement 和/或批量更新语句（包括插入语句和删除语句）吗？</li>
  </ul>
  
<p>基于以上需求，有下列已重载的多个 openSession() 方法供使用。</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">()</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="kwd">boolean</span><span class="pln"> autoCommit</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">Connection</span><span class="pln"> connection</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">TransactionIsolationLevel</span><span class="pln"> level</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">ExecutorType</span><span class="pln"> execType</span><span class="pun">,</span><span class="pln"> </span><span class="typ">TransactionIsolationLevel</span><span class="pln"> level</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">ExecutorType</span><span class="pln"> execType</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">ExecutorType</span><span class="pln"> execType</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> autoCommit</span><span class="pun">)</span><span class="pln">
</span><span class="typ">SqlSession</span><span class="pln"> openSession</span><span class="pun">(</span><span class="typ">ExecutorType</span><span class="pln"> execType</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Connection</span><span class="pln"> connection</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Configuration</span><span class="pln"> getConfiguration</span><span class="pun">();</span></pre></div>
  
<p>默认的 openSession() 方法没有参数，它会创建具备如下特性的 SqlSession：</p>
  
<ul>
    
<li>事务作用域<u>将会</u>开启（也就是不自动提交）。</li>
    
<li>将由当前环境配置的 DataSource 实例中获取 Connection 对象。</li>
    
<li>事务隔离级别将会使用驱动或数据源的默认设置。</li>
    
<li>预处理语句不会被复用，也不会批量处理更新。</li>
  </ul>
  
<p>相信你已经能从方法签名中知道这些方法的区别。向 <tt>autoCommit</tt> 可选参数传递 <tt>true</tt> 值即可开启自动提交功能。若要使用自己的 <tt>Connection</tt> 实例，传递一个 <tt>Connection</tt> 实例给 <tt>connection</tt> 参数即可。注意，我们没有提供同时设置 <tt>Connection</tt> 和 <tt>autoCommit</tt> 的方法，这是因为 MyBatis 会依据传入的 Connection 来决定是否启用 autoCommit。对于事务隔离级别，MyBatis 使用了一个 Java 枚举包装器来表示，称为 <tt>TransactionIsolationLevel</tt>，事务隔离级别支持 JDBC 的五个隔离级别（<tt>NONE</tt>、<tt>READ_UNCOMMITTED</tt>、<tt>READ_COMMITTED</tt>、<tt>REPEATABLE_READ</tt> 和 <tt>SERIALIZABLE</tt>），并且与预期的行为一致。</p>
  
<p>你可能对 <tt>ExecutorType</tt> 参数感到陌生。这个枚举类型定义了三个值:
  </p>
  
<ul>
    
<li><tt>ExecutorType.SIMPLE</tt>：该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句。</li>
    
<li><tt>ExecutorType.REUSE</tt>：该类型的执行器会复用预处理语句。</li>
    
<li><tt>ExecutorType.BATCH</tt>：该类型的执行器会批量执行所有更新语句，如果 SELECT 在多个更新中间执行，将在必要时将多条更新语句分隔开来，以方便理解。</li>
  </ul>
  
<p><span class="label important">提示</span> 在 SqlSessionFactory 中还有一个方法我们没有提及，就是 getConfiguration()。这个方法会返回一个 Configuration 实例，你可以在运行时使用它来检查 MyBatis 的配置。
  </p>
  
<p><span class="label important">提示</span> 如果你使用过 MyBatis 的旧版本，可能还记得 session、事务和批量操作是相互独立的。在新版本中则不是这样。上述三者都包含在 session 作用域内。你不必分别处理事务或批量操作就能得到想要的全部效果。
  </p>

  </div>
<div class="section">
<h4><a name="SqlSession"></a>SqlSession</h4>
  
<p>正如之前所提到的，SqlSession 在 MyBatis 中是非常强大的一个类。它包含了所有执行语句、提交或回滚事务以及获取映射器实例的方法。</p>
  
<p>SqlSession 类的方法超过了 20 个，为了方便理解，我们将它们分成几种组别。</p>

  
<div class="section">
<h5><a name="a.E8.AF.AD.E5.8F.A5.E6.89.A7.E8.A1.8C.E6.96.B9.E6.B3.95"></a>语句执行方法</h5>
  
<p>这些方法被用来执行定义在 SQL 映射 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。你可以通过名字快速了解它们的作用，每一方法都接受语句的 ID 以及参数对象，参数可以是原始类型（支持自动装箱或包装类）、JavaBean、POJO 或 Map。</p>
  
<div class="source"><pre class="prettyprint"><span class="tag">&lt;T&gt;</span><span class="pln"> T selectOne(String statement, Object parameter)
</span><span class="tag">&lt;E&gt;</span><span class="pln"> List</span><span class="tag">&lt;E&gt;</span><span class="pln"> selectList(String statement, Object parameter)
</span><span class="tag">&lt;T&gt;</span><span class="pln"> Cursor</span><span class="tag">&lt;T&gt;</span><span class="pln"> selectCursor(String statement, Object parameter)
</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> Map</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)</span></pre></div>
  
<p>selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象或 null 值。如果返回值多于一个，就会抛出异常。如果你不知道返回对象会有多少，请使用 selectList。如果需要查看某个对象是否存在，最好的办法是查询一个 count 值（0 或 1）。selectMap 稍微特殊一点，它会将返回对象的其中一个属性作为 key 值，将对象作为 value 值，从而将多个结果集转为 Map 类型值。由于并不是所有语句都需要参数，所以这些方法都具有一个不需要参数的重载形式。
  </p>
  
<p>游标（Cursor）与列表（List）返回的结果相同，不同的是，游标借助迭代器实现了数据的惰性加载。</p>
  
<div class="source"><pre class="prettyprint"><span class="kwd">try</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Cursor</span><span class="pun">&lt;</span><span class="typ">MyEntity</span><span class="pun">&gt;</span><span class="pln"> entities </span><span class="pun">=</span><span class="pln"> session</span><span class="pun">.</span><span class="pln">selectCursor</span><span class="pun">(</span><span class="pln">statement</span><span class="pun">,</span><span class="pln"> param</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">MyEntity</span><span class="pln"> entity</span><span class="pun">:</span><span class="pln">entities</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="com">// 处理单个实体</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre></div>
  
<p>insert、update 以及 delete 方法返回的值表示受该语句影响的行数。</p>
  
<div class="source"><pre class="prettyprint"><span class="tag">&lt;T&gt;</span><span class="pln"> T selectOne(String statement)
</span><span class="tag">&lt;E&gt;</span><span class="pln"> List</span><span class="tag">&lt;E&gt;</span><span class="pln"> selectList(String statement)
</span><span class="tag">&lt;T&gt;</span><span class="pln"> Cursor</span><span class="tag">&lt;T&gt;</span><span class="pln"> selectCursor(String statement)
</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> Map</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> selectMap(String statement, String mapKey)
int insert(String statement)
int update(String statement)
int delete(String statement)</span></pre></div>
  
<p>最后，还有 select 方法的三个高级版本，它们允许你限制返回行数的范围，或是提供自定义结果处理逻辑，通常在数据集非常庞大的情形下使用。
  </p>
  
<div class="source"><pre class="prettyprint"><span class="tag">&lt;E&gt;</span><span class="pln"> List</span><span class="tag">&lt;E&gt;</span><span class="pln"> selectList (String statement, Object parameter, RowBounds rowBounds)
</span><span class="tag">&lt;T&gt;</span><span class="pln"> Cursor</span><span class="tag">&lt;T&gt;</span><span class="pln"> selectCursor(String statement, Object parameter, RowBounds rowBounds)
</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> Map</span><span class="tag">&lt;K</span><span class="pln">,</span><span class="atn">V</span><span class="tag">&gt;</span><span class="pln"> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler</span><span class="tag">&lt;T&gt;</span><span class="pln"> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler</span><span class="tag">&lt;T&gt;</span><span class="pln"> handler)</span></pre></div>
  
<p>RowBounds 参数会告诉 MyBatis 略过指定数量的记录，并限制返回结果的数量。RowBounds 类的 offset 和 limit 值只有在构造函数时才能传入，其它时候是不能修改的。</p>

  
<div class="source"><pre class="prettyprint"><span class="kwd">int</span><span class="pln"> offset </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">int</span><span class="pln"> limit </span><span class="pun">=</span><span class="pln"> </span><span class="lit">25</span><span class="pun">;</span><span class="pln">
</span><span class="typ">RowBounds</span><span class="pln"> rowBounds </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">RowBounds</span><span class="pun">(</span><span class="pln">offset</span><span class="pun">,</span><span class="pln"> limit</span><span class="pun">);</span></pre></div>
  
<p>数据库驱动决定了略过记录时的查询效率。为了获得最佳的性能，建议将 ResultSet 类型设置为 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE（换句话说：不要使用 FORWARD_ONLY）。</p>
  
<p>ResultHandler 参数允许自定义每行结果的处理过程。你可以将它添加到 List 中、创建 Map 和 Set，甚至丢弃每个返回值，只保留计算后的统计结果。你可以使用 ResultHandler 做很多事，这其实就是 MyBatis 构建 结果列表的内部实现办法。</p>
  
<p>从版本 3.4.6 开始，<tt>ResultHandler</tt> 会在存储过程的 REFCURSOR 输出参数中传递使用的 <tt>CALLABLE</tt> 语句。</p>
  
<p>它的接口很简单：</p>

  
<div class="source"><pre class="prettyprint"><span class="kwd">package</span><span class="pln"> org</span><span class="pun">.</span><span class="pln">apache</span><span class="pun">.</span><span class="pln">ibatis</span><span class="pun">.</span><span class="pln">session</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">interface</span><span class="pln"> </span><span class="typ">ResultHandler</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">void</span><span class="pln"> handleResult</span><span class="pun">(</span><span class="typ">ResultContext</span><span class="pun">&lt;?</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln"> context</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre></div>
  
<p>ResultContext 参数允许你访问结果对象和当前已被创建的对象数目，另外还提供了一个返回值为 Boolean 的 stop 方法，你可以使用此 stop 方法来停止 MyBatis 加载更多的结果。</p>
  
<p>使用 ResultHandler 的时候需要注意以下两个限制：</p>
  
<ul>
    
<li>使用带 ResultHandler 参数的方法时，收到的数据不会被缓存。</li>
  
<li>当使用高级的结果映射集（resultMap）时，MyBatis 很可能需要数行结果来构造一个对象。如果你使用了 ResultHandler，你可能会接收到关联（association）或者集合（collection）中尚未被完整填充的对象。</li>
  </ul>

  </div>
<div class="section">
<h5><a name="a.E7.AB.8B.E5.8D.B3.E6.89.B9.E9.87.8F.E6.9B.B4.E6.96.B0.E6.96.B9.E6.B3.95"></a>立即批量更新方法</h5>
  
<p>当你将 <tt>ExecutorType</tt> 设置为 <tt>ExecutorType.BATCH</tt> 时，可以使用这个方法清除（执行）缓存在 JDBC 驱动类中的批量更新语句。</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">BatchResult</span><span class="pun">&gt;</span><span class="pln"> flushStatements</span><span class="pun">()</span></pre></div>

  </div>
<div class="section">
<h5><a name="a.E4.BA.8B.E5.8A.A1.E6.8E.A7.E5.88.B6.E6.96.B9.E6.B3.95"></a>事务控制方法</h5>
  
<p>
    有四个方法用来控制事务作用域。当然，如果你已经设置了自动提交或你使用了外部事务管理器，这些方法就没什么作用了。然而，如果你正在使用由 Connection 实例控制的 JDBC 事务管理器，那么这四个方法就会派上用场：
  </p>
  
<div class="source"><pre class="prettyprint"><span class="kwd">void</span><span class="pln"> commit</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> commit</span><span class="pun">(</span><span class="kwd">boolean</span><span class="pln"> force</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> rollback</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> rollback</span><span class="pun">(</span><span class="kwd">boolean</span><span class="pln"> force</span><span class="pun">)</span></pre></div>
  
<p>默认情况下 MyBatis 不会自动提交事务，除非它侦测到调用了插入、更新或删除方法改变了数据库。如果你没有使用这些方法提交修改，那么你可以在 commit 和 rollback 方法参数中传入 true 值，来保证事务被正常提交（注意，在自动提交模式或者使用了外部事务管理器的情况下，设置 force 值对 session 无效）。大部分情况下你无需调用 rollback()，因为 MyBatis 会在你没有调用 commit 时替你完成回滚操作。不过，当你要在一个可能多次提交或回滚的 session 中详细控制事务，回滚操作就派上用场了。</p>
  
<p><span class="label important">提示</span> MyBatis-Spring 和 MyBatis-Guice 提供了声明式事务处理，所以如果你在使用 Mybatis 的同时使用了 Spring 或者 Guice，请参考它们的手册以获取更多的内容。</p>

</div>
<div class="section">
<h5><a name="a.E6.9C.AC.E5.9C.B0.E7.BC.93.E5.AD.98"></a>本地缓存</h5>
  
<p>Mybatis 使用到了两种缓存：本地缓存（local cache）和二级缓存（second level cache）。</p>
  
<p>每当一个新 session 被创建，MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中，所以，当再次执行参数相同的相同查询时，就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚，以及关闭 session 时清空。</p>
  
<p>默认情况下，本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度，所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。</p>
  
<p>注意，如果 localCacheScope 被设置为 SESSION，对于某个对象，MyBatis 将返回在本地缓存中唯一对象的引用。对返回的对象（例如 list）做出的任何修改将会影响本地缓存的内容，进而将会影响到在本次 session 中从缓存返回的值。因此，不要对 MyBatis 所返回的对象作出更改，以防后患。</p>
  
<p>你可以随时调用以下方法来清空本地缓存：</p>
 &nbsp;
<div class="source"><pre class="prettyprint"><span class="kwd">void</span><span class="pln"> clearCache</span><span class="pun">()</span></pre></div>
  </div>
<div class="section">
<h5><a name="a.E7.A1.AE.E4.BF.9D_SqlSession_.E8.A2.AB.E5.85.B3.E9.97.AD"></a>确保 SqlSession 被关闭</h5>
  
<div class="source"><pre class="prettyprint"><span class="kwd">void</span><span class="pln"> close</span><span class="pun">()</span></pre></div>
  
<p>对于你打开的任何 session，你都要保证它们被妥善关闭，这很重要。保证妥善关闭的最佳代码模式是这样的：</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">SqlSession</span><span class="pln"> session </span><span class="pun">=</span><span class="pln"> sqlSessionFactory</span><span class="pun">.</span><span class="pln">openSession</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">(</span><span class="typ">SqlSession</span><span class="pln"> session </span><span class="pun">=</span><span class="pln"> sqlSessionFactory</span><span class="pun">.</span><span class="pln">openSession</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// 假设下面三行代码是你的业务逻辑</span><span class="pln">
    session</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(...);</span><span class="pln">
    session</span><span class="pun">.</span><span class="pln">update</span><span class="pun">(...);</span><span class="pln">
    session</span><span class="pun">.</span><span class="kwd">delete</span><span class="pun">(...);</span><span class="pln">
    session</span><span class="pun">.</span><span class="pln">commit</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre></div>
  
<p><span class="label important">提示</span> 和 SqlSessionFactory 一样，你可以调用当前使用的 SqlSession 的 getConfiguration 方法来获得 Configuration 实例。</p>
  
<div class="source"><pre class="prettyprint"><span class="typ">Configuration</span><span class="pln"> getConfiguration</span><span class="pun">()</span></pre></div>

  </div>
<div class="section">
<h5><a name="a.E4.BD.BF.E7.94.A8.E6.98.A0.E5.B0.84.E5.99.A8"></a>使用映射器</h5>
  
<div class="source"><pre class="prettyprint"><span class="tag">&lt;T&gt;</span><span class="pln"> T getMapper(Class</span><span class="tag">&lt;T&gt;</span><span class="pln"> type)</span></pre></div>
  
<p>上述的各个 insert、update、delete 和 select 方法都很强大，但也有些繁琐，它们并不符合类型安全，对你的 IDE 和单元测试也不是那么友好。因此，使用映射器类来执行映射语句是更常见的做法。</p>
  
<p>我们已经在之前的入门章节中见到过一个使用映射器的示例。一个映射器类就是一个仅需声明与 SqlSession 方法相匹配方法的接口。下面的示例展示了一些方法签名以及它们是如何映射到 SqlSession 上的。</p>
  
<div class="source"><pre class="prettyprint"><span class="kwd">public</span><span class="pln"> </span><span class="kwd">interface</span><span class="pln"> </span><span class="typ">AuthorMapper</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// (Author) selectOne("selectAuthor",5);</span><span class="pln">
  </span><span class="typ">Author</span><span class="pln"> selectAuthor</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> id</span><span class="pun">);</span><span class="pln">
  </span><span class="com">// (List&lt;Author&gt;) selectList(“selectAuthors”)</span><span class="pln">
  </span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">Author</span><span class="pun">&gt;</span><span class="pln"> selectAuthors</span><span class="pun">();</span><span class="pln">
  </span><span class="com">// (Map&lt;Integer,Author&gt;) selectMap("selectAuthors", "id")</span><span class="pln">
  </span><span class="lit">@MapKey</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">)</span><span class="pln">
  </span><span class="typ">Map</span><span class="pun">&lt;</span><span class="typ">Integer</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Author</span><span class="pun">&gt;</span><span class="pln"> selectAuthors</span><span class="pun">();</span><span class="pln">
  </span><span class="com">// insert("insertAuthor", author)</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> insertAuthor</span><span class="pun">(</span><span class="typ">Author</span><span class="pln"> author</span><span class="pun">);</span><span class="pln">
  </span><span class="com">// updateAuthor("updateAuthor", author)</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> updateAuthor</span><span class="pun">(</span><span class="typ">Author</span><span class="pln"> author</span><span class="pun">);</span><span class="pln">
  </span><span class="com">// delete("deleteAuthor",5)</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> deleteAuthor</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> id</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre></div>
  
<p>总之，每个映射器方法签名应该匹配相关联的 SqlSession 方法，字符串参数 ID 无需匹配。而是由方法名匹配映射语句的 ID。</p>
  
<p>此外，返回类型必须匹配期望的结果类型，返回单个值时，返回类型应该是返回值的类，返回多个值时，则为数组或集合类，另外也可以是游标（Cursor）。所有常用的类型都是支持的，包括：原始类型、Map、POJO 和 JavaBean。</p>
  
<p><span class="label important">提示</span> 映射器接口不需要去实现任何接口或继承自任何类。只要方法签名可以被用来唯一识别对应的映射语句就可以了。</p>
  
<p><span class="label important">提示</span> 映射器接口可以继承自其他接口。在使用 XML 来绑定映射器接口时，保证语句处于合适的命名空间中即可。唯一的限制是，不能在两个具有继承关系的接口中拥有相同的方法签名（这是潜在的危险做法，不可取）。</p>
  
<p>你可以传递多个参数给一个映射器方法。在多个参数的情况下，默认它们将会以 param 加上它们在参数列表中的位置来命名，比如：#{param1}、#{param2}等。如果你想（在有多个参数时）自定义参数的名称，那么你可以在参数上使用 @Param("paramName") 注解。</p>
  
<p>你也可以给方法传递一个 RowBounds 实例来限制查询结果。</p>

</div>
<div class="section">
<h5><a name="a.E6.98.A0.E5.B0.84.E5.99.A8.E6.B3.A8.E8.A7.A3"></a>映射器注解</h5>
  
<p>设计初期的 MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的，映射语句也是定义在 XML 中的。而在 MyBatis 3 中，我们提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。它是 XML 和注解配置的基础。注解提供了一种简单且低成本的方式来实现简单的映射语句。</p>
  
<p><span class="label important">提示</span> 不幸的是，Java 注解的表达能力和灵活性十分有限。尽管我们花了很多时间在调查、设计和试验上，但最强大的 MyBatis 映射并不能用注解来构建——我们真没开玩笑。而 C# 属性就没有这些限制，因此 MyBatis.NET 的配置会比 XML 有更大的选择余地。虽说如此，基于 Java 注解的配置还是有它的好处的。</p>
  
<p><b>注解如下表所示：</b></p>
  

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;

 &nbsp; &nbsp; &nbsp; &nbsp;
<table border="0" class="table table-striped">
    <thead>
      
<tr class="a">
        
<th>注解</th>
        
<th>使用对象</th>
        
<th>XML 等价形式</th>
        
<th>描述</th>
    </tr>
    </thead>
    <tbody>
      
<tr class="b">
        
<td><tt>@CacheNamespace</tt></td>
        
<td><tt>类</tt></td>
        
<td><tt>&lt;cache&gt;</tt></td><td>为给定的命名空间（比如类）配置缓存。属性：<tt>implemetation</tt>、<tt>eviction</tt>、<tt>flushInterval</tt>、<tt>size</tt>、<tt>readWrite</tt>、<tt>blocking</tt>、<tt>properties</tt>。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@Property</tt></td>
        
<td>N/A</td>
        
<td><tt>&lt;property&gt;</tt></td><td>指定参数值或占位符（placeholder）（该占位符能被 <tt>mybatis-config.xml</tt> 内的配置属性替换）。属性：<tt>name</tt>、<tt>value</tt>。（仅在 MyBatis 3.4.2 以上可用）</td>
      </tr>
      
<tr class="b">
        
<td><tt>@CacheNamespaceRef</tt></td>
        
<td><tt>类</tt></td>
        
<td><tt>&lt;cacheRef&gt;</tt></td>
        
<td>引用另外一个命名空间的缓存以供使用。注意，即使共享相同的全限定类名，在 XML 映射文件中声明的缓存仍被识别为一个独立的命名空间。属性：<tt>value</tt>、<tt>name</tt>。如果你使用了这个注解，你应设置 <tt>value</tt> 或者&nbsp;<tt>name</tt> 属性的其中一个。<tt>value</tt> 属性用于指定能够表示该命名空间的 Java 类型（命名空间名就是该 Java 类型的全限定类名），<tt>name</tt> 属性（这个属性仅在 MyBatis 3.4.2 以上可用）则直接指定了命名空间的名字。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@ConstructorArgs</tt></td>
        
<td><tt>方法</tt></td>
        
<td><tt>&lt;constructor&gt;</tt></td><td>收集一组结果以传递给一个结果对象的构造方法。属性：<tt>value</tt>，它是一个 <tt>Arg</tt> 数组。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@Arg</tt></td>
        
<td>N/A</td>
        
<td>

<ul>

<li><tt>&lt;arg&gt;</tt></li>

<li><tt>&lt;idArg&gt;</tt></li>
</ul>
        </td><td>ConstructorArgs 集合的一部分，代表一个构造方法参数。属性：<tt>id</tt>、<tt>column</tt>、<tt>javaType</tt>、<tt>jdbcType</tt>、<tt>typeHandler</tt>、<tt>select</tt>、<tt>resultMap</tt>。id 属性和 XML 元素 <tt>&lt;idArg&gt;</tt> 相似，它是一个布尔值，表示该属性是否用于唯一标识和比较对象。从版本 3.5.4 开始，该注解变为可重复注解。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@TypeDiscriminator</tt></td>
        
<td><tt>方法</tt></td>
        
<td><tt>&lt;discriminator&gt;</tt></td><td>决定使用何种结果映射的一组取值（case）。属性：<tt>column</tt>、<tt>javaType</tt>、<tt>jdbcType</tt>、<tt>typeHandler</tt>、<tt>cases</tt>。cases 属性是一个 <tt>Case</tt> 的数组。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@Case</tt></td>
        
<td>N/A</td>
        
<td><tt>&lt;case&gt;</tt></td><td>表示某个值的一个取值以及该取值对应的映射。属性：<tt>value</tt>、<tt>type</tt>、<tt>results</tt>。results 属性是一个 <tt>Results</tt> 的数组，因此这个注解实际上和 <tt>ResultMap</tt> 很相似，由下面的 <tt>Results</tt> 注解指定。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@Results</tt></td>
        
<td><tt>方法</tt></td>
        
<td><tt>&lt;resultMap&gt;</tt></td>
        
<td>一组结果映射，指定了对某个特定结果列，映射到某个属性或字段的方式。属性：<tt>value</tt>、<tt>id</tt>。value 属性是一个 <tt>Result</tt> 注解的数组。而 id 属性则是结果映射的名称。从版本 3.5.4 开始，该注解变为可重复注解。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@Result</tt></td>
        
<td>N/A</td>
        
<td>

<ul>

<li><tt>&lt;result&gt;</tt></li>

<li><tt>&lt;id&gt;</tt></li>
</ul>
        </td><td>在列和属性或字段之间的单个结果映射。属性：<tt>id</tt>、<tt>column</tt>、<tt>javaType</tt>、<tt>jdbcType</tt>、<tt>typeHandler</tt>、<tt>one</tt>、<tt>many</tt>。id 属性和 XML 元素 <tt>&lt;id&gt;</tt> 相似，它是一个布尔值，表示该属性是否用于唯一标识和比较对象。one 属性是一个关联，和 <tt>&lt;association&gt;</tt> 类似，而 many 属性则是集合关联，和 <tt>&lt;collection&gt;</tt> 类似。这样命名是为了避免产生名称冲突。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@One</tt></td>
        
<td>N/A</td>
        
<td><tt>&lt;association&gt;</tt></td><td>复杂类型的单个属性映射。属性：<tt>select</tt>，指定可加载合适类型实例的映射语句（也就是映射器方法）全限定名；<tt>fetchType</tt>，指定在该映射中覆盖全局配置参数 <tt>lazyLoadingEnabled</tt>。<span class="label important">提示</span> 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@Many</tt></td>
        
<td>N/A</td>
        
<td><tt>&lt;collection&gt;</tt></td><td>复杂类型的集合属性映射。属性：<tt>select</tt>，指定可加载合适类型实例集合的映射语句（也就是映射器方法）全限定名；<tt>fetchType</tt>，指定在该映射中覆盖全局配置参数 <tt>lazyLoadingEnabled</tt>。<span class="label important">提示</span> 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@MapKey</tt></td>
        
<td><tt>方法</tt></td>
        
<td></td>
        
<td>供返回值为 Map 的方法使用的注解。它使用对象的某个属性作为 key，将对象 List 转化为 Map。属性：<tt>value</tt>，指定作为 Map 的 key 值的对象属性名。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@Options</tt></td>
        
<td><tt>方法</tt></td>
        
<td>映射语句的属性</td><td>该注解允许你指定大部分开关和配置选项，它们通常在映射语句上作为属性出现。与在注解上提供大量的属性相比，<tt>Options</tt> 注解提供了一致、清晰的方式来指定选项。属性：<tt>useCache=true</tt>、<tt>flushCache=FlushCachePolicy.DEFAULT</tt>、<tt>resultSetType=DEFAULT</tt>、<tt>statementType=PREPARED</tt>、<tt>fetchSize=-1</tt>、<tt>timeout=-1</tt>、<tt>useGeneratedKeys=false</tt>、<tt>keyProperty=""</tt>、<tt>keyColumn=""</tt>、<tt>resultSets=""</tt>。注意，Java 注解无法指定 <tt>null</tt> 值。因此，一旦你使用了 <tt>Options</tt> 注解，你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的非预期行为。<br><br>
 &nbsp; &nbsp; &nbsp; &nbsp;注意：<tt>keyColumn</tt> 属性只在某些数据库中有效（如 Oracle、PostgreSQL 等）。要了解更多关于 <tt>keyColumn</tt> 和&nbsp;<tt>keyProperty</tt> 可选值信息，请查看“insert, update 和 delete”一节。</td>
      </tr>
      
<tr class="a">
        
<td>

<ul>

<li><tt>@Insert</tt></li>

<li><tt>@Update</tt></li>

<li><tt>@Delete</tt></li>

<li><tt>@Select</tt></li>
</ul>
        </td>
        
<td><tt>方法</tt></td>
        
<td>

<ul>

<li><tt>&lt;insert&gt;</tt></li>

<li><tt>&lt;update&gt;</tt></li>

<li><tt>&lt;delete&gt;</tt></li>

<li><tt>&lt;select&gt;</tt></li>
</ul>
        </td><td>每个注解分别代表将会被执行的 SQL 语句。它们用字符串数组（或单个字符串）作为参数。如果传递的是字符串数组，字符串数组会被连接成单个完整的字符串，每个字符串之间加入一个空格。这有效地避免了用 Java 代码构建 SQL 语句时产生的“丢失空格”问题。当然，你也可以提前手动连接好字符串。属性：<tt>value</tt>，指定用来组成单个 SQL 语句的字符串数组。</td>
      </tr>
      
<tr class="b">
        
<td>

<ul>

<li><tt>@InsertProvider</tt></li>

<li><tt>@UpdateProvider</tt></li>

<li><tt>@DeleteProvider</tt></li>

<li><tt>@SelectProvider</tt></li>
</ul>
        </td>
        
<td><tt>方法</tt></td>
        
<td>

<ul>

<li><tt>&lt;insert&gt;</tt></li>

<li><tt>&lt;update&gt;</tt></li>

<li><tt>&lt;delete&gt;</tt></li>

<li><tt>&lt;select&gt;</tt></li>
</ul>
        </td><td>允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法，以供运行时执行。（从 MyBatis 3.4.6 开始，可以使用 <tt>CharSequence</tt> 代替&nbsp;<tt>String</tt> 来作为返回类型）。当执行映射语句时，MyBatis 会实例化注解指定的类，并调用注解指定的方法。你可以通过 <tt>ProviderContext</tt> 传递映射方法接收到的参数、"Mapper interface type" 和 "Mapper method"（仅在 MyBatis 3.4.5 以上支持）作为参数。（MyBatis 3.4 以上支持传入多个参数）属性：<tt>type</tt>、<tt>method</tt>。<tt>type</tt> 属性用于指定类名。<tt>method</tt> 用于指定该类的方法名（从版本 3.5.1 开始，可以省略 <tt>method</tt> 属性，MyBatis 将会使用 <tt>ProviderMethodResolver</tt> 接口解析方法的具体实现。如果解析失败，MyBatis 将会使用名为 <tt>provideSql</tt> 的降级实现）。<span class="label important">提示</span> 接下来的“SQL 语句构建器”一章将会讨论该话题，以帮助你以更清晰、更便于阅读的方式构建动态 SQL。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@Param</tt></td>
        
<td><tt>参数</tt></td>
        
<td>N/A</td><td>如果你的映射方法接受多个参数，就可以使用这个注解自定义每个参数的名字。否则在默认情况下，除 <tt>RowBounds</tt> 以外的参数会以 "param" 加参数位置被命名。例如 <tt>#{param1}</tt>, <tt>#{param2}</tt>。如果使用了 <tt>@Param("person")</tt>，参数就会被命名为 <tt>#{person}</tt>。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@SelectKey</tt></td>
        
<td><tt>方法</tt></td>
        
<td><tt>&lt;selectKey&gt;</tt></td><td>这个注解的功能与 <tt>&lt;selectKey&gt;</tt> 标签完全一致。该注解只能在 <tt>@Insert</tt> 或 <tt>@InsertProvider</tt> 或 <tt>@Update</tt> 或 <tt>@UpdateProvider</tt> 标注的方法上使用，否则将会被忽略。如果标注了 <tt>@SelectKey</tt> 注解，MyBatis 将会忽略掉由 <tt>@Options</tt> 注解所设置的生成主键或设置（configuration）属性。属性：<tt>statement</tt> 以字符串数组形式指定将会被执行的 SQL 语句，<tt>keyProperty</tt> 指定作为参数传入的对象对应属性的名称，该属性将会更新成新的值，<tt>before</tt> 可以指定为 <tt>true</tt> 或&nbsp;<tt>false</tt> 以指明 SQL 语句应被在插入语句的之前还是之后执行。<tt>resultType</tt> 则指定&nbsp;<tt>keyProperty</tt> 的 Java 类型。<tt>statementType</tt> 则用于选择语句类型，可以选择 <tt>STATEMENT</tt>、<tt>PREPARED</tt> 或 <tt>CALLABLE</tt> 之一，它们分别对应于 <tt>Statement</tt>、<tt>PreparedStatement</tt> 和 <tt>CallableStatement</tt>。默认值是 <tt>PREPARED</tt>。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@ResultMap</tt></td>
        
<td><tt>方法</tt></td>
        
<td>N/A</td>
        
<td>这个注解为 <tt>@Select</tt> 或者 <tt>@SelectProvider</tt> 注解指定 XML 映射中 <tt>&lt;resultMap&gt;</tt> 元素的 id。这使得注解的 select 可以复用已在 XML 中定义的 ResultMap。如果标注的 select 注解中存在 <tt>@Results</tt> 或者 <tt>@ConstructorArgs</tt> 注解，这两个注解将被此注解覆盖。</td>
      </tr>
      
<tr class="b">
        
<td><tt>@ResultType</tt></td>
        
<td><tt>方法</tt></td>
        
<td>N/A</td><td>在使用了结果处理器的情况下，需要使用此注解。由于此时的返回类型为 void，所以 Mybatis 需要有一种方法来判断每一行返回的对象类型。如果在 XML 有对应的结果映射，请使用 <tt>@ResultMap</tt> 注解。如果结果类型在 XML 的 <tt>&lt;select&gt;</tt> 元素中指定了，就不需要使用其它注解了。否则就需要使用此注解。比如，如果一个标注了 @Select 的方法想要使用结果处理器，那么它的返回类型必须是 void，并且必须使用这个注解（或者 @ResultMap）。这个注解仅在方法返回类型是 void 的情况下生效。</td>
      </tr>
      
<tr class="a">
        
<td><tt>@Flush</tt></td>
        
<td><tt>方法</tt></td>
        
<td>N/A</td><td>如果使用了这个注解，定义在 Mapper 接口中的方法就能够调用 <tt>SqlSession#flushStatements()</tt> 方法。（Mybatis 3.3 以上可用）</td>
    </tr>
    </tbody>
  </table>

  </div>
<div class="section">
<h5><a name="a.E6.98.A0.E5.B0.84.E6.B3.A8.E8.A7.A3.E7.A4.BA.E4.BE.8B"></a>映射注解示例</h5>

<p>这个例子展示了如何使用 @SelectKey 注解来在插入前读取数据库序列的值：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@Insert</span><span class="pun">(</span><span class="str">"insert into table3 (id, name) values(#{nameId}, #{name})"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@SelectKey</span><span class="pun">(</span><span class="pln">statement</span><span class="pun">=</span><span class="str">"call next value for TestSequence"</span><span class="pun">,</span><span class="pln"> keyProperty</span><span class="pun">=</span><span class="str">"nameId"</span><span class="pun">,</span><span class="pln"> before</span><span class="pun">=</span><b><span class="kwd">true</span></b><span class="pun">,</span><span class="pln"> resultType</span><span class="pun">=</span><b><span class="kwd">int</span><span class="pun">.</span><span class="kwd">class</span></b><span class="pun">)</span><span class="pln">
</span><b><span class="kwd">int</span></b><span class="pln"> insertTable3</span><span class="pun">(</span><span class="typ">Name</span><span class="pln"> name</span><span class="pun">);</span></pre></div>

<p>这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库自增列的值：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@Insert</span><span class="pun">(</span><span class="str">"insert into table2 (name) values(#{name})"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@SelectKey</span><span class="pun">(</span><span class="pln">statement</span><span class="pun">=</span><span class="str">"call identity()"</span><span class="pun">,</span><span class="pln"> keyProperty</span><span class="pun">=</span><span class="str">"nameId"</span><span class="pun">,</span><span class="pln"> before</span><span class="pun">=</span><b><span class="kwd">false</span></b><span class="pun">,</span><span class="pln"> resultType</span><span class="pun">=</span><b><span class="kwd">int</span><span class="pun">.</span><span class="kwd">class</span></b><span class="pun">)</span><span class="pln">
</span><b><span class="kwd">int</span></b><span class="pln"> insertTable2</span><span class="pun">(</span><span class="typ">Name</span><span class="pln"> name</span><span class="pun">);</span></pre></div>

<p>这个例子展示了如何使用 <tt>@Flush</tt> 注解来调用 <tt>SqlSession#flushStatements()</tt>：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@Flush</span><span class="pln">
</span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">BatchResult</span><span class="pun">&gt;</span><span class="pln"> flush</span><span class="pun">();</span></pre></div>

<p>这些例子展示了如何通过指定 @Result 的 id 属性来命名结果集：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@Results</span><span class="pun">(</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> </span><span class="str">"userResult"</span><span class="pun">,</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="lit">@Result</span><span class="pun">(</span><span class="pln">property </span><span class="pun">=</span><span class="pln"> </span><span class="str">"id"</span><span class="pun">,</span><span class="pln"> column </span><span class="pun">=</span><span class="pln"> </span><span class="str">"uid"</span><span class="pun">,</span><span class="pln"> id </span><span class="pun">=</span><span class="pln"> </span><b><span class="kwd">true</span></b><span class="pun">),</span><span class="pln">
  </span><span class="lit">@Result</span><span class="pun">(</span><span class="pln">property </span><span class="pun">=</span><span class="pln"> </span><span class="str">"firstName"</span><span class="pun">,</span><span class="pln"> column </span><span class="pun">=</span><span class="pln"> </span><span class="str">"first_name"</span><span class="pun">),</span><span class="pln">
  </span><span class="lit">@Result</span><span class="pun">(</span><span class="pln">property </span><span class="pun">=</span><span class="pln"> </span><span class="str">"lastName"</span><span class="pun">,</span><span class="pln"> column </span><span class="pun">=</span><span class="pln"> </span><span class="str">"last_name"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="lit">@Select</span><span class="pun">(</span><span class="str">"select * from users where id = #{id}"</span><span class="pun">)</span><span class="pln">
</span><span class="typ">User</span><span class="pln"> getUserById</span><span class="pun">(</span><span class="typ">Integer</span><span class="pln"> id</span><span class="pun">);</span><span class="pln">

</span><span class="lit">@Results</span><span class="pun">(</span><span class="pln">id </span><span class="pun">=</span><span class="pln"> </span><span class="str">"companyResults"</span><span class="pun">)</span><span class="pln">
</span><span class="lit">@ConstructorArgs</span><span class="pun">({</span><span class="pln">
  </span><span class="lit">@Arg</span><span class="pun">(</span><span class="pln">column </span><span class="pun">=</span><span class="pln"> </span><span class="str">"cid"</span><span class="pun">,</span><span class="pln"> javaType </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Integer</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> id </span><span class="pun">=</span><span class="pln"> </span><b><span class="kwd">true</span></b><span class="pun">),</span><span class="pln">
  </span><span class="lit">@Arg</span><span class="pun">(</span><span class="pln">column </span><span class="pun">=</span><span class="pln"> </span><span class="str">"name"</span><span class="pun">,</span><span class="pln"> javaType </span><span class="pun">=</span><span class="pln"> </span><span class="typ">String</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">)</span><span class="pln">
</span><span class="pun">})</span><span class="pln">
</span><span class="lit">@Select</span><span class="pun">(</span><span class="str">"select * from company where id = #{id}"</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Company</span><span class="pln"> getCompanyById</span><span class="pun">(</span><span class="typ">Integer</span><span class="pln"> id</span><span class="pun">);</span></pre></div>

<p>这个例子展示了如何使用单个参数的 @SqlProvider 注解：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@SelectProvider</span><span class="pun">(</span><span class="pln">type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">UserSqlBuilder</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> method </span><span class="pun">=</span><span class="pln"> </span><span class="str">"buildGetUsersByName"</span><span class="pun">)</span><span class="pln">
</span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">User</span><span class="pun">&gt;</span><span class="pln"> getUsersByName</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> name</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserSqlBuilder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> buildGetUsersByName</span><span class="pun">(</span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> SQL</span><span class="pun">(){{</span><span class="pln">
      SELECT</span><span class="pun">(</span><span class="str">"*"</span><span class="pun">);</span><span class="pln">
      FROM</span><span class="pun">(</span><span class="str">"users"</span><span class="pun">);</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">name </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        WHERE</span><span class="pun">(</span><span class="str">"name like #{value} || '%'"</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
      ORDER_BY</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}}.</span><span class="pln">toString</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre></div>

<p>这个例子展示了如何使用多个参数的 @SqlProvider 注解：</p>
  
<div class="source"><pre class="prettyprint"><span class="lit">@SelectProvider</span><span class="pun">(</span><span class="pln">type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">UserSqlBuilder</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> method </span><span class="pun">=</span><span class="pln"> </span><span class="str">"buildGetUsersByName"</span><span class="pun">)</span><span class="pln">
</span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">User</span><span class="pun">&gt;</span><span class="pln"> getUsersByName</span><span class="pun">(</span><span class="pln">
    </span><span class="lit">@Param</span><span class="pun">(</span><span class="str">"name"</span><span class="pun">)</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> </span><span class="lit">@Param</span><span class="pun">(</span><span class="str">"orderByColumn"</span><span class="pun">)</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> orderByColumn</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserSqlBuilder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

  </span><span class="com">// 如果不使用 @Param，就应该定义与 mapper 方法相同的参数</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> buildGetUsersByName</span><span class="pun">(</span><span class="pln">
      </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> orderByColumn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> SQL</span><span class="pun">(){{</span><span class="pln">
      SELECT</span><span class="pun">(</span><span class="str">"*"</span><span class="pun">);</span><span class="pln">
      FROM</span><span class="pun">(</span><span class="str">"users"</span><span class="pun">);</span><span class="pln">
      WHERE</span><span class="pun">(</span><span class="str">"name like #{name} || '%'"</span><span class="pun">);</span><span class="pln">
      ORDER_BY</span><span class="pun">(</span><span class="pln">orderByColumn</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}}.</span><span class="pln">toString</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

  </span><span class="com">// 如果使用 @Param，就可以只定义需要使用的参数</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> buildGetUsersByName</span><span class="pun">(</span><span class="lit">@Param</span><span class="pun">(</span><span class="str">"orderByColumn"</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> orderByColumn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> SQL</span><span class="pun">(){{</span><span class="pln">
      SELECT</span><span class="pun">(</span><span class="str">"*"</span><span class="pun">);</span><span class="pln">
      FROM</span><span class="pun">(</span><span class="str">"users"</span><span class="pun">);</span><span class="pln">
      WHERE</span><span class="pun">(</span><span class="str">"name like #{name} || '%'"</span><span class="pun">);</span><span class="pln">
      ORDER_BY</span><span class="pun">(</span><span class="pln">orderByColumn</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}}.</span><span class="pln">toString</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre></div>

    
<p>以下例子展示了 <tt>ProviderMethodResolver</tt>（3.5.1 后可用）的默认实现使用方法：
    </p>
    
<div class="source"><pre class="prettyprint"><span class="lit">@SelectProvider</span><span class="pun">(</span><span class="typ">UserSqlProvider</span><span class="pun">.</span><span class="kwd">class</span><span class="pun">)</span><span class="pln">
</span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">User</span><span class="pun">&gt;</span><span class="pln"> getUsersByName</span><span class="pun">(</span><span class="typ">String</span><span class="pln"> name</span><span class="pun">);</span><span class="pln">

</span><span class="com">// 在你的 provider 类中实现 ProviderMethodResolver 接口</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserSqlProvider</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">ProviderMethodResolver</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">// 默认实现中，会将映射器方法的调用解析到实现的同名方法上</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> getUsersByName</span><span class="pun">(</span><span class="kwd">final</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> SQL</span><span class="pun">(){{</span><span class="pln">
      SELECT</span><span class="pun">(</span><span class="str">"*"</span><span class="pun">);</span><span class="pln">
      FROM</span><span class="pun">(</span><span class="str">"users"</span><span class="pun">);</span><span class="pln">
      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">name </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        WHERE</span><span class="pun">(</span><span class="str">"name like #{value} || '%'"</span><span class="pun">);</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
      ORDER_BY</span><span class="pun">(</span><span class="str">"id"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}}.</span><span class="pln">toString</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre></div>
  </div></div></div>

  </div>
  

        </div>
      </div>
    </div>
    <hr>
    <footer>
      <div class="container-fluid">
        <div class="row-fluid">
            <p>Copyright ©2009–2020
<a href="http://www.mybatis.org/">MyBatis.org</a>.
All rights reserved.</p>
        </div>
      </div>
    </footer>
  

<div class="xl-chrome-ext-bar" id="xl_chrome_ext_{4DB361DE-01F7-4376-B494-639E489D19ED}" style="display: none;">
      <div class="xl-chrome-ext-bar__logo"></div>

      <a id="xl_chrome_ext_download" href="javascript:;" class="xl-chrome-ext-bar__option">下载视频</a>
      <a id="xl_chrome_ext_close" href="javascript:;" class="xl-chrome-ext-bar__close"></a>
    </div></body></html>